/**
 * @file        load_so.c
 * @brief       XXXX
 * @note        XXXX
 * @author      靳普诏(puzhao.jin@hopechart.com)
 * @date        2025/02/25
 * @version     1.0

 * @par         修改日志
 * <table>
 * <tr><th>Date         <th>Version     <th>Author      <th> Description
 * <tr><td>2025/02/25   <td>1.0         <td>靳普诏       <td> 创建初始版本
 * @copyright 杭州鸿泉物联网技术股份有限公司
 */
 
#include "load_so.h"
#include <stdio.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#define SO_HANDLE HMODULE
#define SO_OPEN(name) LoadLibraryA(name)
#define SO_CLOSE FreeLibrary
#define SO_GET_SYMBOL GetProcAddress
#define SO_GET_ERROR() GetLastError()
#else
#include <dlfcn.h>
#define SO_HANDLE void*
#define SO_OPEN(name) dlopen(name, RTLD_LAZY)
#define SO_CLOSE dlclose
#define SO_GET_SYMBOL dlsym
#define SO_GET_ERROR() dlerror()
#endif

static char last_error[256] = {0};

void* load_so_open(const char* so_path) {
    if (!so_path) {
        snprintf(last_error, sizeof(last_error), "Invalid parameter: so_path is NULL");
        return NULL;
    }

    SO_HANDLE handle = SO_OPEN(so_path);
    if (!handle) {
#ifdef _WIN32
        DWORD error = SO_GET_ERROR();
        snprintf(last_error, sizeof(last_error), "Failed to load library: error code %lu", error);
#else
        const char* error = SO_GET_ERROR();
        snprintf(last_error, sizeof(last_error), "Failed to load library: %s", error ? error : "unknown error");
#endif
        return NULL;
    }
    return handle;
}

void* load_so_get_symbol(void* handle, const char* symbol_name) {
    if (!handle || !symbol_name) {
        snprintf(last_error, sizeof(last_error), "Invalid parameter: handle or symbol_name is NULL");
        return NULL;
    }

    void* symbol = SO_GET_SYMBOL((SO_HANDLE)handle, symbol_name);
    if (!symbol) {
#ifdef _WIN32
        DWORD error = SO_GET_ERROR();
        snprintf(last_error, sizeof(last_error), "Failed to get symbol: error code %lu", error);
#else
        const char* error = SO_GET_ERROR();
        snprintf(last_error, sizeof(last_error), "Failed to get symbol: %s", error ? error : "unknown error");
#endif
        return NULL;
    }
    return symbol;
}

int load_so_close(void* handle) {
    if (!handle) {
        snprintf(last_error, sizeof(last_error), "Invalid parameter: handle is NULL");
        return -1;
    }

    if (SO_CLOSE((SO_HANDLE)handle) == 0) {
        return 0;
    }

#ifdef _WIN32
    DWORD error = SO_GET_ERROR();
    snprintf(last_error, sizeof(last_error), "Failed to close library: error code %lu", error);
#else
    const char* error = SO_GET_ERROR();
    snprintf(last_error, sizeof(last_error), "Failed to close library: %s", error ? error : "unknown error");
#endif
    return -1;
}

const char* load_so_error(void) {
    return last_error;
}
